import json

from django.http import JsonResponse
from django.views import View
from django.contrib.auth.hashers import make_password
from django.utils.decorators import method_decorator
from django.db import transaction

from gongyequ.models import User
from gongyequ.utils import validators
from gongyequ.utils.page import get_pagination
from gongyequ.decorator import login_required
from gongyequ.decorator import permission_required


@method_decorator(login_required(), name='dispatch')
@method_decorator(permission_required('admin'), name='dispatch')
class UserView(View):
    def get(self, request, id=None):
        if id is not None:
            return self._get_user(request, id)
        else:
            return self._list_users(request)

    def post(self, request, id=None, action=None):
        if action:
            if action == 'lock':
                return self._lock_user(request, id)
            elif action == 'unlock':
                return self._unlock_user(request, id)

        return self._create_user(request)

    def patch(self, request, id):
        return self._patch_user(request, id)

    def delete(self, request, id):
        return self._delete_user(request, id)

    def _list_users(self, request):
        """用户列表
        GET /industrialapi/admin/users
        Query String:
            username='用户名'
            phone='手机号'
        """
        username = request.GET.get('username')
        phone = request.GET.get('phone')

        users = User.objects.all()

        if username:
            users = users.filter(username__icontains=username)

        if phone:
            users = users.filter(phone__icontains=phone)

        data = dict(message='ok', status=True, code=200)
        page, _, pagination = get_pagination(request, users)

        data_list = []
        for user in page:
            data_list.append(user.serialize())

        data['data'] = data_list
        data['pagination'] = pagination

        return JsonResponse(data=data)

    @transaction.atomic
    def _patch_user(self, request, id):
        """编辑用户
        PATCH /industrialapi/admin/users/<int:id>

        Body{
            username='用户名'
            password='密码'
            phone='手机号'
            is_active=True or False
        }
        """
        try:
            user = User.objects.get(id=id)
        except User.DoesNotExist:
            return JsonResponse(dict(message='not found', status=False, code=400, data=[]))

        if user.is_admin:
            return JsonResponse(dict(message='该用户为管理员，无法更改', status=False, code=400, data=[]))

        update_args = []

        data = json.loads(request.body.decode('utf-8'))

        if 'username' in data:
            user.username = data.get('username')
            update_args.append('username')

        if 'password' in data:
            user.password = make_password(data.get('password'))
            update_args.append('password')

        if 'phone' in data:
            user.phone = data.get('phone')
            update_args.append('phone')
            update_args.append('phone_validated')

        if 'is_active' in data:
            user.is_active = data.get('is_active',True)
            update_args.append('is_active')

        if update_args:
            user.save(update_fields=update_args)

        serialize_data = dict(message='ok', status=True, code=200)
        serialize_data['data'] = user.serialize()
        return JsonResponse(data=serialize_data)

    def _get_user(self, request, id):
        """获取指定用户信息
        GET /industrialapi/admin/users/<int:id>
        """
        try:
            user = User.objects.get(id=id)
        except User.DoesNotExist:
            return JsonResponse(dict(message='not found', status=False, code=400, data=[]))

        data = dict(message='ok', status=True, code=200)
        data['data'] = user.serialize()
        return JsonResponse(data=data)

    @transaction.atomic
    def _create_user(self, request):
        """创建用户
        POST /industrialapi/admin/users
        Body{
            username='用户名'
            password='密码'
            phone='手机号'
            is_active=True or False //是否启用该账号
        }
        """
        data = json.loads(request.body.decode('utf-8'))
        username = data.get('username')
        password = data.get('password')
        phone = data.get('phone')
        is_active = data.get('is_active', True)

        create_args = dict()

        if not username or not password or not phone:
            return JsonResponse(dict(message='用户名密码和手机号不能为空', status=False, code=400, data=[]))

        if not validators.is_valid_phone(phone):
            return JsonResponse(dict(message='请输入正确的手机号', status=False, code=400, data=[]))

        create_args['username'] = username
        # 注：这里不用担心 password 为 None，如果 password 为 None，django 会自动设置为不可用密码
        create_args['password'] = password
        create_args['phone'] = phone
        create_args['phone_validated'] = True

        if is_active:
            create_args['is_active'] = True
        else:
            create_args['is_active'] = False

        user = User.objects.create_user(**create_args)

        data = dict(message='ok', status=True, code=200)
        data['data'] = user.serialize()
        return JsonResponse(data=data)

    def _delete_user(self, request, id):
        """删除用户
        DELETE /industrialapi/admin/users/<int:id>
        """
        try:
            user = User.objects.get(id=id)
        except User.DoesNotExist:
            return JsonResponse(dict(message='not found', status=False, code=400, data=[]))

        user.is_delete = True
        user.save()

        return JsonResponse(dict(message='ok', status=True, code=200, data=[]))

    def _lock_user(self, request, id):
        """锁定指定用户
        POST /industrialapi/admin/users/<int:id>/lock
        """
        try:
            user = User.objects.get(id=id)
        except User.DoesNotExist:
            return JsonResponse(dict(message='not found', status=False, code=400, data=[]))

        if not user.is_active:
            return JsonResponse(dict(message='用户已经被锁定', status=False, code=400, data=[]))

        user.is_active = False
        user.save(update_fields=['is_active'])

        return JsonResponse(dict(message='ok', status=True, code=200, data=[]))

    def _unlock_user(self, request, id):
        """启用指定用户
        POST /industrialapi/admin/users/<int:id>/unlock
        """
        try:
            user = User.objects.get(id=id)
        except User.DoesNotExist:
            return JsonResponse(dict(message='not found', status=False, code=400, data=[]))

        if user.is_active:
            return JsonResponse(dict(message='该用户未被锁定', status=False, code=400, data=[]))

        user.is_active = True
        user.save(update_fields=['is_active'])

        return JsonResponse(dict(message='ok', status=True, code=200, data=[]))
